package com.faner.fast.excel.helper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.faner.fast.excel.annotation.ResponseExcel;
import com.faner.fast.excel.event.AnalysisEventAutoListener;
import com.faner.fast.excel.function.CiFunction;
import com.faner.fast.excel.kit.ExcelException;
import com.faner.fast.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;


@Slf4j
public final class EasyExcelHelper {


    /**
     * 将错误信息下载
     * @param response
     * @param clazz  bean对象
     * @param example 列表数据
     * @param <T>
     */
    public static <T> void downloadError(HttpServletResponse response,
                                         Class<?> clazz,
                                         List<T> example) {
        ResponseExcel excel = getExcel(clazz);
        ResponseExcel superExcel = getSuperExcel(clazz);
        ExcelWriterBuilder(response, excel.name() + superExcel.name(), excel.suffix())
                .sheet(excel.sheet()[0]+superExcel.sheet()[0])
                .useDefaultStyle(true)
                .head(clazz)
                .doWrite(CollectionUtil.isEmpty(example) ? Lists.newArrayList() : example);
    }

    public static void read(String filePath, AnalysisEventAutoListener listener) throws IOException {
        //文件file转MultipartFile
        File file = new File(filePath);
        MultipartFile multipartFile = FileUtil.toMultipartFile(file);
        String fileName = multipartFile.getOriginalFilename();
        if (StringUtils.isBlank(fileName)) {
            throw new ExcelException("文件名不合法");
        }
        String finalFileName = fileName.toLowerCase();
        if (finalFileName.endsWith(ExcelTypeEnum.XLS.getValue()) || finalFileName.endsWith(ExcelTypeEnum.XLSX.getValue())) {
            EasyExcel.read(multipartFile.getInputStream(), listener.getClazz(), listener)
                    .sheet()
                    .doRead();
        } else {
            throw new ExcelException(StrUtil.format("只支持{},{}文件导入",ExcelTypeEnum.XLS.getValue(),ExcelTypeEnum.XLSX.getValue()));
        }
    }


    private static ExcelWriterBuilder ExcelWriterBuilder(HttpServletResponse response,
                                                         String fileName,
                                                         ExcelTypeEnum excelTypeEnum) {
        return EasyExcel.write(OutputStream.apply(response, fileName, excelTypeEnum));
    }

    public static CiFunction<HttpServletResponse, String, ExcelTypeEnum, OutputStream> OutputStream = (response, fileName, excelTypeEnum) -> {
        try {
            return getOutputStream(response, fileName, excelTypeEnum);
        } catch (IOException e) {
            throw new ExcelException("获取文件失败");
        }
    };

    private static OutputStream getOutputStream(HttpServletResponse response,
                                                String fileName,
                                                ExcelTypeEnum excelTypeEnum) throws IOException {
        try {
            String finalFileName = URLEncoder.encode((fileName + System.currentTimeMillis() + excelTypeEnum.getValue()), "UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");
            response.setHeader("Content-Disposition", "attachment;filename=" + finalFileName);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            return response.getOutputStream();
        } catch (IOException e) {
            log.error("获取输出流异常：", e);
            throw e;
        }
    }

    public static ResponseExcel getExcel(Class<?> clazz) {
        // 获取类excel文件名
        ResponseExcel excel = clazz.getAnnotation(ResponseExcel.class);
        if (excel == null) {
            throw new ExcelException(String.format("class [%s] @ResponseExcel Annotation is Empty", clazz.getSimpleName()));
        }
        return excel;
    }

    public static ResponseExcel getSuperExcel(Class<?> clazz) {
        // 获取类excel文件名
        ResponseExcel excel = clazz.getSuperclass().getAnnotation(ResponseExcel.class);
        if (excel == null) {
            throw new ExcelException(String.format("superclass [%s] @ResponseExcel Annotation is Empty", clazz.getSimpleName()));
        }
        return excel;
    }

}
